#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstring>
#include <memory>
#include <unistd.h>
#include <pthread.h>
#include <functional>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <jsoncpp/json/json.h>

#include "Log.hpp"
#include "Socket.hpp"
#include "TcpServer.hpp"

const std::string http_sep = "\r\n";
const std::string webRoot = "./wwwroot/";
const std::string header_sep = ": ";

void testsstream()
{
    std::string s = "oo hh xx";
    std::stringstream ss(s);

    std::string s1, s2, s3;
    ss >> s1 >> s2 >> s3;

    printf("%s\n", s1.c_str());
    printf("%s\n", s2.c_str());
    printf("%s\n", s3.c_str());
}
////////////////////////////////////////////////////////////////////////////////////////////////

// get / http/1.1
class HttpRequest
{
private:
    std::string GetOneLine(std::string &message)
    {
        size_t pos = message.find(http_sep);
        if (pos == std::string::npos)
            return "";

        std::string ret = message.substr(0, pos);
        message.erase(0, pos + 2);

        return ret;
    }

public:
    HttpRequest()
    {
    }

    // /a/b/c.html
    std::string GetUrl()
    {
        std::string path = webRoot;
        if (_url == "/")
        {
            path += "index.html";
        }
        else
        {
            path += _url;
        }

        return path;
    }

    void Deserialize(std::string &message)
    {
        _fline = GetOneLine(message);

        // handle first line
        std::stringstream ss(_fline);
        ss >> _method >> _url >> _version;

        while (true)
        {
            std::string line = GetOneLine(message);
            if (line == "")
                break;
            _header += line;
        }

        _text = message;
    }
    std::string GetSuffix()
    {
        _suffix = ".html";

        size_t pos = _url.rfind('.');
        if (pos == std::string::npos)
            return _suffix;

        _suffix = _url.substr(pos);
        return _suffix;
    }

    void print()
    {
        printf("method: %s, path: %s, version: %s\n", _method.c_str(), _url.c_str(), _version.c_str());
        printf("====================================\n");
        std::cout << _header << std::endl;
        std::cout << _text << std::endl;
    }

    std::string _method;
    std::string _url;
    std::string _version;

    std::string _suffix;

    std::string _fline;
    std::string _header;
    std::string _text;
};

// HTTP/1.0 200 OK
class HttpResponse
{
private:
public:
    HttpResponse()
    {
    }

    void AddHeader(std::string k, std::string v)
    {
        std::string line = k + header_sep + v;
        _header += line;
        _header += http_sep;
    }

    std::string FillText(std::string path)
    {
        std::ifstream in(path, std::ios::binary | std::ios::in);
        if (!in.is_open())
        {
            LOG(ERROR, "open file %s failed\n", path.c_str());
            return "";
        }

        in.seekg(0, std::ios::end);
        size_t length = in.tellg();
        in.seekg(0, std::ios::beg);

        _text.resize(length);
        in.read((char *)_text.c_str(), length);
        return _text;
    }

    std::string Serialize()
    {
        _version = "HTTP/1.1";
        _code = "200";
        _desc = "OK";

        _fline = "HTTP/1.0 200 OK";

        std::string message = _fline + http_sep + _header + http_sep + _text;
        return message;
    }

private:
    std::string _version;
    std::string _code;
    std::string _desc;

    std::string _fline;
    std::string _header;
    std::string _text;
};

void testHttpRequest()
{
    std::string message = "GET / HTTP/1.1\r\n";

    // std::cout << message << std::endl;

    HttpRequest hreq;
    HttpResponse hres;
    hreq.Deserialize(message);
    std::string url = hreq.GetUrl();
    std::cout << "url: " << url << std::endl;
    std::string suffix = hreq.GetSuffix();
    std::cout << "suffix: " << suffix << std::endl;
    std::string text = hres.FillText(url);
    hres.AddHeader("Content-Length", std::to_string(text.size()));

    std::cout << hres.Serialize() << std::endl;
}

std::string GetSuffix(std::string _suffix, std::string _url)
{
    _suffix = ".html";

    size_t pos = _url.rfind('.');
    if (pos == std::string::npos)
        return _suffix;

    _suffix = _url.substr(pos);
    return _suffix;
}

void testsuffix()
{
    std::cout << GetSuffix("", "/a/b/c.jpg") << std::endl;
}

int main()
{
    testHttpRequest();

    return 0;
}

// void Reconnect()
// {
//     int cnt = 0;
//     while(true)
//     {
//         Connect();
//         if(_status == connected)
//         {
//             std::cout << "重连成功\n";
//             break;
//         }
//         if(cnt > maxconnum)
//         {
//             std::cout << "网络已断开\n";
//             _status = closed;
//             break;
//         }
//         cnt++;
//         std::cout << "网络波动，正在尝试第" << cnt << "次重连\n";
//         sleep(retry_interval);
//     }
// }

// void CloseConnect()
// {
//     if(_sockfd > 0)
//     {
//         close(sockfd);
//         _status = c
//     }
// }